-- DPSCheck/auras.lua

local check_options = {}
local check_aura_spell_names = {}
local buffed_spell_auras = {}

local relevance_checks = {}
relevance_checks['spell_id'] = function(v)
                                 return IsSpellKnown(v)
                               end
relevance_checks['talent'] = function(v)
                               return DPSCheck_CharacterData.current_state.talents[v] > 0
                             end

function DPSCheck.check_auras(spell_name)
  if buffed_spell_auras[spell_name] == nil then
    return
  end

  for _, check_spell_id in ipairs(buffed_spell_auras[spell_name]) do
    local _, check_spell_name = DPSCheck.populate_spell(check_spell_id)

    local options = check_options[check_spell_id]

    local relevant = true
    for option_name, option_func in pairs(relevance_checks) do
      if relevant and options[option_name] ~= nil then
        relevant = relevant and option_func(options[option_name])
      end
    end

    if relevant then
      local found = false

      for _, check_aura_spell_name in ipairs(check_aura_spell_names[check_spell_id]) do
        if not found then
          local aura_temp = UnitAura(options.unit, check_aura_spell_name, nil, options.filter)
          if aura_temp ~= nil then
            found = true
          end
        end
      end

      if found then
        DPSCheck.record_action({'auras', check_spell_name})
      else
        DPSCheck.record_action({'auras', check_spell_name}, spell_name)
      end
    end
  end
end

------------------------------------------------------------
-- events --------------------------------------------------
------------------------------------------------------------

DPSCheck.push_event_pattern(function (current_state, combat_segment, input_event)
                              DPSCheck.check_auras(input_event.spell_name)
                            end,
                            {event = 'UNIT_SPELLCAST_SENT', unit_id = 'player'})

------------------------------------------------------------
-- setup functions -----------------------------------------
------------------------------------------------------------

local function add_aura_check(check_spell_id, description, aura_spell_ids, buffed_spell_ids, options, unit, filter, prefix)
  local _, check_spell_name = DPSCheck.populate_spell(check_spell_id)
  if check_spell_name == nil then
    print(format('no spell found for spell id %d', check_spell_id))
    return
  end

  -- check for duplicates

  if options[check_spell_id] ~= nil then
    print('duplicate aura checks setup for ' .. check_spell_name)
    return
  end

  -- save options

  local saved_options = {}
  for k, v in pairs(options) do
    saved_options[k] = v
  end
  saved_options.unit = unit
  saved_options.filter = filter
  saved_options.prefix = prefix

  check_options[check_spell_id] = saved_options

  -- register matching auras

  check_aura_spell_names[check_spell_id] = {}
  for _, aura_spell_id in pairs(aura_spell_ids) do
    _, aura_spell_name = DPSCheck.populate_spell(aura_spell_id)
    table.insert(check_aura_spell_names[check_spell_id], aura_spell_name)
  end

  -- register buffed spells

  for _, buffed_spell_id in ipairs(buffed_spell_ids) do
    local _, buffed_spell_name = DPSCheck.populate_spell(buffed_spell_id)
  
    if buffed_spell_auras[buffed_spell_name] == nil then
      buffed_spell_auras[buffed_spell_name] = {}
    end
    table.insert(buffed_spell_auras[buffed_spell_name], check_spell_id)
  end

  local function temp_func (combat_segment)
    return DPSCheck.report_mistakes(DPSCheck_get3(combat_segment, 'statistics', 'auras', check_spell_name), prefix)
  end

  DPSCheck.push_report_function(check_spell_name, 'Buff/Debuff Checks', description, temp_func)
end

function DPSCheck.add_buff_check(check_spell_id, description, aura_spell_ids, buffed_spell_ids, options)
  add_aura_check(check_spell_id, description, aura_spell_ids, buffed_spell_ids, options, 'player', 'HELPFUL', 'Missing Buff')
end

function DPSCheck.add_debuff_check(check_spell_id, description, aura_spell_ids, buffed_spell_ids, options)
  local filter = 'HARMFUL'
  if options.selfonly then
    filter = filter .. '|PLAYER'
  end
  
  add_aura_check(check_spell_id, description, aura_spell_ids, buffed_spell_ids, options, 'target', filter, 'Missing Debuff')
end

